package com.kaede.game.netty;

import com.google.protobuf.ByteString;
import com.kaede.game.config.HandlerRegister;
import com.kaede.game.config.HandlerWrapper;
import com.kaede.game.dto.CommonRequestOuterClass;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;


//标示一个ChannelHandler可以被多个 Channel 安全地共享
@Sharable
@Component
public class ServerHandler extends ChannelInboundHandlerAdapter {

    public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private HandlerRegister handlerRegister;

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        logger.info("server: channel active");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        logger.info("server: receive message");
        CommonRequestOuterClass.CommonRequest commonRequest = (CommonRequestOuterClass.CommonRequest)msg;
        String handerUrl = commonRequest.getAddr();
        HandlerWrapper handlerWrapper = handlerRegister.getGameHandlerWrapperMap().get(handerUrl);
        Method handerMethod = handlerWrapper.getMethod();
        Class<?> paramType = handerMethod.getParameterTypes()[0];
        Method parseFrom = paramType.getMethod("parseFrom", ByteString.class);
        Object data = parseFrom.invoke(null, commonRequest.getData());
        Object responseData = handerMethod.invoke(handlerWrapper.getBean(), data);
        ctx.write(responseData);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx)
            throws Exception {
        //将未决消息冲刷到远程节点，并且关闭该 Channel
//        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx,
        Throwable cause) {
        //打印异常栈跟踪
        cause.printStackTrace();
        //关闭该Channel
        ctx.close();
    }
}
